namespace C1.Win.C1FlexGrid.Util
{
    using System;
    using System.Drawing;
    using System.Windows.Forms;

    internal class Win32
    {
        internal const int EM_CHARFROMPOS = 0xd7;
        internal const int EM_GETLINECOUNT = 0xba;
        internal const int EM_LINEFROMCHAR = 0xc9;
        internal const int WM_CHAR = 0x102;
        internal const int WM_ERASEBKGND = 20;
        internal const int WM_KEYDOWN = 0x100;
        internal const int WM_LBUTTONDOWN = 0x201;
        internal const int WM_LBUTTONUP = 0x202;
        internal const int WS_BORDER = 0x800000;
        internal const int WS_CLIPCHILDREN = 0x2000000;
        internal const int WS_CLIPSIBLINGS = 0x4000000;
        internal const int WS_EX_CLIENTEDGE = 0x200;
        internal const int WS_EX_STATICEDGE = 0x20000;
        internal const int WS_HSCROLL = 0x100000;
        internal const int WS_VSCROLL = 0x200000;

        internal static void DrawBorder3D(Graphics g, Rectangle rc, Border3DStyle style)
        {
            Pen control = SystemPens.Control;
            Pen controlLightLight = SystemPens.ControlLightLight;
            Pen controlDark = SystemPens.ControlDark;
            Pen controlDarkDark = SystemPens.ControlDarkDark;
            rc.Width--;
            rc.Height--;
            switch (style)
            {
                case Border3DStyle.Bump:
                    UpperCorner(g, rc, control);
                    LowerCorner(g, rc, controlDarkDark);
                    rc.Inflate(-1, -1);
                    UpperCorner(g, rc, controlDarkDark);
                    LowerCorner(g, rc, control);
                    return;

                case Border3DStyle.Etched:
                    UpperCorner(g, rc, controlDark);
                    LowerCorner(g, rc, controlLightLight);
                    rc.Inflate(-1, -1);
                    UpperCorner(g, rc, controlLightLight);
                    LowerCorner(g, rc, controlDark);
                    return;

                case Border3DStyle.Flat:
                    g.DrawRectangle(controlDark, rc);
                    rc.Inflate(-1, -1);
                    g.DrawRectangle(control, rc);
                    return;

                case Border3DStyle.Raised:
                    UpperCorner(g, rc, control);
                    LowerCorner(g, rc, controlDarkDark);
                    rc.Inflate(-1, -1);
                    UpperCorner(g, rc, controlLightLight);
                    LowerCorner(g, rc, controlDark);
                    return;

                case Border3DStyle.RaisedInner:
                    UpperCorner(g, rc, controlLightLight);
                    LowerCorner(g, rc, controlDark);
                    return;

                case Border3DStyle.RaisedOuter:
                    UpperCorner(g, rc, control);
                    LowerCorner(g, rc, controlDarkDark);
                    return;

                case Border3DStyle.Sunken:
                    UpperCorner(g, rc, controlDark);
                    LowerCorner(g, rc, controlLightLight);
                    rc.Inflate(-1, -1);
                    UpperCorner(g, rc, controlDarkDark);
                    LowerCorner(g, rc, control);
                    return;

                case Border3DStyle.SunkenInner:
                    UpperCorner(g, rc, controlDarkDark);
                    LowerCorner(g, rc, control);
                    return;

                case Border3DStyle.SunkenOuter:
                    UpperCorner(g, rc, controlDark);
                    LowerCorner(g, rc, controlLightLight);
                    return;
            }
            throw new Exception("Unsupported BorderStyle.");
        }

        internal static IntPtr IntPtrFromPoint(Point pt)
        {
            return (IntPtr) (pt.X | (pt.Y << 0x10));
        }

        private static void LowerCorner(Graphics g, Rectangle rc, Pen pen)
        {
            g.DrawLine(pen, rc.Left, rc.Bottom, rc.Right, rc.Bottom);
            g.DrawLine(pen, rc.Right, rc.Bottom, rc.Right, rc.Top);
        }

        internal static Point PointFromIntPtr(IntPtr intPtr)
        {
            return new Point(((int) intPtr) & 0xff, ((int) intPtr) >> 0x10);
        }

        private static void UpperCorner(Graphics g, Rectangle rc, Pen pen)
        {
            g.DrawLine(pen, rc.Left, rc.Bottom, rc.Left, rc.Top);
            g.DrawLine(pen, rc.Left, rc.Top, rc.Right, rc.Top);
        }
    }
}

